package etc.obu.service.impl;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.util.Log;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.UUID;

import etc.obu.service.IResultHandler;
import etc.obu.service.model.AcSynchronization;
import etc.obu.service.model.CommonState;
import etc.obu.service.model.ServiceStatus;
import etc.obu.service.utils.ObuSerialization;

/**
 * 与obu通信的通信员
 */
@SuppressWarnings("all")
public class ObuMessenger extends BluetoothGattCallback {
    private final String tag = ObuMessenger.class.getName();
    private final String uuid = "0000FEE7-0000-1000-8000-00805F9B34FB";
    private final String write_uuid = "0000FFE1-0000-1000-8000-00805F9B34FB";
    private final String read_uuid = "0000FEC8-0000-1000-8000-00805F9B34FB";
    private IResultHandler resultHandler;
    private CommonState state;
    private BluetoothDevice targetObu;
    private BluetoothGatt gatt;
    private BluetoothGattCharacteristic writeCharac;
    private AcSynchronization acSynchronization=new AcSynchronization();

    public ObuMessenger(IResultHandler handler, BluetoothDevice targetObu) {
        resultHandler = handler;
        this.targetObu = targetObu;
    }

    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        if (newState == BluetoothGatt.STATE_CONNECTED) {
            Log.i(tag, "已成功连接设备");
            gatt.discoverServices();
        } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
            this.state = CommonState.error;
            this.gatt = null;
            this.writeCharac = null;
            if(acSynchronization.getState()==CommonState.占用){
                Method callBack = acSynchronization.getCallBack();
                try {
                    acSynchronization.getCallBack().invoke(resultHandler,ServiceStatus.fail("连接已断开"));
                    acSynchronization.setState(CommonState.不占用);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }else{
                resultHandler.onConnectionDevice(ServiceStatus.fail("连接已断开", targetObu));
            }
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        BluetoothGattService gattService = gatt.getService(UUID.fromString(uuid));
        BluetoothGattCharacteristic notify = gattService.getCharacteristic(UUID.fromString(read_uuid));
        gatt.setCharacteristicNotification(notify, true);
        writeCharac = gattService.getCharacteristic(UUID.fromString(write_uuid));
        this.gatt = gatt;
        this.state = CommonState.finish;
        resultHandler.onConnectionDevice(ServiceStatus.success("已连接成功", targetObu));
    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        Log.i(tag, characteristic.getValue().toString());
    }

    @Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
        Log.i(tag,descriptor.getCharacteristic().getValue().toString());
    }

    public CommonState getState() {
        return state;
    }

    public void setState(CommonState state) {
        this.state = state;
    }

    /**
     * TODO 发送消息与接收消息做到同步，需要有对应关系从而可以反应给前端，需要一个锁（是否占用，回调的方法）
     */
    public void sendMessage(String msg, Method method) {
        synchronized (acSynchronization){   //防止外层建立多线程使用
            new Thread(()->{
                Log.i(tag,"发送信息");
                long start=System.currentTimeMillis();
                while(true){
                    if(acSynchronization.getState()==CommonState.不占用){
                        acSynchronization.setState(CommonState.占用);
                        acSynchronization.setCallBack(method);
                        writeCharac.setValue(ObuSerialization.serialize(msg));
                        gatt.writeCharacteristic(writeCharac);
                        break;
                    }else if(this.state==null||this.state==CommonState.error){
                        break;
                    }else if(System.currentTimeMillis()-start>10000){
                        try {
                            method.invoke(resultHandler,ServiceStatus.fail("调用超时"));
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }
    }
}
